package com.gdgk.shop.service.impl;


import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;


import com.gdgk.shop.bean.model.ScoreImportDetail;
import com.gdgk.shop.bean.model.ScoreImportRecord;
import com.gdgk.shop.common.response.ResponseEnum;
import com.gdgk.shop.common.response.ServerResponseEntity;
import com.gdgk.shop.dao.ScoreImportDetailMapper;
import com.gdgk.shop.dao.ScoreImportRecordMapper;
import com.gdgk.shop.dao.UserMapper;
import com.gdgk.shop.service.ScoreService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;


@Service
@Slf4j
public class ScoreServiceImpl implements ScoreService {

    @Autowired
    private ScoreImportRecordMapper scoreImportRecordMapper;

    @Autowired
    private ScoreImportDetailMapper scoreImportDetailMapper;

    @Autowired
    private UserMapper userMapper;


    @Override
    public Long resolveExcel(MultipartFile file) throws Exception {

        try (InputStream inputStream = file.getInputStream()) {
            // 检查文件类型和名称（如果需要）
            String fileName = file.getOriginalFilename();
            String fileContentType = file.getContentType();

            Workbook workbook = WorkbookFactory.create(inputStream);
            Sheet sheet = workbook.getSheetAt(0); // 假设数据在第一个工作表中
            DataFormatter formatter = new DataFormatter();

            // 一、写 记录表
            // 1.生成要写入的 记录表 数据库对象
            ScoreImportRecord record = new ScoreImportRecord();
            record.setOperaBy(123L);
            record.setFileName(fileName); // 文件名称
            record.setStatus("0");
            Date date = new Date();
            record.setCreateTime(date);
            record.setOperaTime(date);


            // 2.写入数据库
            int rowsAffected = scoreImportRecordMapper.insertRecord(record);
            // 拿到插入记录的id
            Long recordId = record.getId();
            // System.out.println("插入记录 返回的数是：" + rowsAffected);
            // System.out.println("插入记录后返回的id是：" + recordId);

            // 二、写 明细表
            for (Row row : sheet) {   // 一行表示一条明细
                if (row.getRowNum() == 0 || row.getRowNum() == 1) {
                    // 跳过前两行
                    continue;
                }
                // 1.生成要写入的 记录表 数据库对象
                ScoreImportDetail detail = new ScoreImportDetail();
                int numericCellValue = 0;
                try {
                    numericCellValue = (int) row.getCell(1).getNumericCellValue();
                    detail.setStatus("0");
                } catch (Exception exception) {
                    log.error("积分导入格式异常");
                    detail.setStatus("e");
                    detail.setRemark("积分导入格式异常");
                }
//                String mobileNumber = row.getCell(0).getStringCellValue();
//                System.out.println(row.getCell(0).getNumericCellValue());
//                String mobileNumber = String.valueOf(row.getCell(0).getNumericCellValue());
                Cell cell = row.getCell(0);
                String mobileNumber = formatter.formatCellValue(cell);
                System.out.println(mobileNumber);

                if (StringUtils.isBlank(mobileNumber) && mobileNumber.length() != 11) {
                    detail.setRemark("手机号码格式异常;" + detail.getRemark());
                }
                detail.setMobileNumber(mobileNumber); // 假设手机号码在第一列
                detail.setScore(numericCellValue); // 假设积分在第二列
                detail.setRecordId(recordId);
                detail.setChangeType("0");  // 先默认都是 增加积分 TODO 后续如果添加批量扣减积分再加上
                Date date1 = new Date();
                record.setCreateTime(date1);
                // 2.写入数据库
                scoreImportDetailMapper.insertDetail(detail);
            }
        } catch (IOException e) {
            // 处理异常
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 提供给初次绑定手机号操作 绑定积分
     *
     * @param mobileNumber
     * @param openId
     * @throws Exception
     */
    @Override
    @Transactional
    public boolean bindingScoreByMobile(String mobileNumber, String openId) throws Exception {

        // 1.查询detail表，求出与手机号匹配并且status=0的积分总和,
        Integer totalScore = scoreImportDetailMapper.sumScoreByMobileNumberAndStatus(mobileNumber);
        System.out.println("totalScore:" + totalScore);
        if(totalScore == null || totalScore == 0){
            log.info("用户积分绑定操作 未找到该用户积分变更记录");
            return false;
        }
        // 2.如果totalScore大于0，说明有批量变更积分的记录，该用户必定有openId
        // 那么就要 将积分绑定到用户表中，同时更新detail表  将与手机号匹配的记录的status置为1
        boolean result = false;
        try {
            result = this.binding(openId, mobileNumber, totalScore);
        } catch (Exception exception) {
            exception.printStackTrace();
            log.info("用户积分绑定操作 状态修改时异常");
        }
        return result;
    }

    /**
     * 提供给支付操作
     *
     * @param mobileNumber
     * @param score
     * @throws Exception
     */
    @Override
    @Transactional
    public ServerResponseEntity subtractScoreByPay(String mobileNumber, Integer score) throws Exception {
        ServerResponseEntity serverResponseEntity = new ServerResponseEntity();

        // 判断手机号：
        if (StringUtils.isBlank(mobileNumber) && mobileNumber.length() != 11) {
            // 返回手机号格式错误
            serverResponseEntity.showFailMsg("用户号码格式异常! ");
            log.info("用户号码格式异常! ");
            return serverResponseEntity;
        }
        // 判断剩余积分：
        int residualScore = userMapper.selectScoreByPhoneNumber(mobileNumber);
        if (score > residualScore) {
            // 返回 剩余积分 和 积分不足提示
            serverResponseEntity.showFailMsg("积分不足，支付失败！ 剩余积分:" + residualScore);
            log.info("积分不足，支付失败！ 剩余积分:" + residualScore);
            return serverResponseEntity;
        }
        // 1.创建明细对象
        ScoreImportDetail detail = new ScoreImportDetail();
        detail.setMobileNumber(mobileNumber);
        detail.setScore(score);
        detail.setStatus("1");
        Date date = new Date();
        detail.setCreateTime(date);
        detail.setRecordId(null);
        detail.setRemark("积分支付");
        // 2.写入数据库
        scoreImportDetailMapper.insertDetail(detail);
        // 3.去用户表扣减用户积分
        int result = userMapper.subtractScore(mobileNumber, score);
        if ( result > 0 ) {
            serverResponseEntity.success(ResponseEnum.OK);
            log.info("用户手机号" + mobileNumber + "，支付积分:" + score);
        } else
            serverResponseEntity.showFailMsg("支付失败！");
            log.info("支付失败！");
        // System.out.println("扣减积分返回值：" + result);
        return serverResponseEntity;

    }


//    @Override
//    @Transactional
//    public void pointsDistribution(List<ScoreImportDetail> detailList, Long recordId) throws Exception {
//
//        for (int i = 0; i < detailList.size(); i++) {
//            ScoreImportDetail detail = detailList.get(i);
//            // (0)拿到手机号和积分
//            String mobileNumber = detail.getMobileNumber();
//            Integer score = detail.getScore();
//            // （1）根据手机号 修改用户表 用户积分
//            if (detail.getChangeType().equals("0")) { // 0-增加积分
//                userMapper.addScore(mobileNumber, score);
//            } else if (detail.getChangeType().equals("1")) {// 1-扣减积分（暂时不启用）
//                userMapper.subtractScore(mobileNumber, score);
//            } else {
//                // 抛出异常
//                System.out.println("积分变更类型不明确");
//            }
//            // （2）根据手机号 修改明细表 状态从0变1
//            scoreImportDetailMapper.changeStatusByMobileNumber(mobileNumber);
//        }
//        // （3）执行完明细表，再修改记录表：根据record_id 修改记录表 状态从0变1 (单独写为函数)
//        scoreImportRecordMapper.changeStatusById(recordId);
//
//    }

    @Override
    public void pointsDistribution(List<ScoreImportDetail> detailList, Long recordId) throws Exception {

        for (int i = 0; i < detailList.size(); i++) {
            ScoreImportDetail detail = detailList.get(i);
            // 手机号和积分
            String mobileNumber = detail.getMobileNumber();
            Integer score = detail.getScore();
            // 增加用户积分操作
            try {
                this.add(mobileNumber, score);
            } catch (Exception exception) {
                exception.printStackTrace();
                // MyBatis-Plus 为简化开发、提高效率，提供了条件构造器 Wrapper，用于构造复杂的SQL查询条件。
                // 这些 Wrapper 允许你以链式调用的方式设置查询条件，从而避免手写大量的XML或注解来定义SQL语句
                UpdateWrapper<ScoreImportDetail> wrapperUpdate = new UpdateWrapper<>();
                wrapperUpdate.eq("id", detail.getId());
                wrapperUpdate.set("status", "e");
                wrapperUpdate.set("remark", "积分增加异常");
                log.info("用户积分增加异常，id :" + detail.getId());
                scoreImportDetailMapper.update(wrapperUpdate);
            }

        }
        // （3）执行完明细表，再修改记录表：根据record_id 修改记录表 状态从0变1 (单独写为函数)
        boolean updateResult = scoreImportRecordMapper.changeStatusById(recordId) > 0;
        log.info("用户积分增加，记录更新: " + updateResult);

    }


    /**
     * 根据手机号查询用户表的用户积分
     * @param mobileNumber
     * @return
     * @throws Exception
     */
    @Override
    public int queryScoreByMobileNumber(String mobileNumber) throws Exception {
        return userMapper.selectScoreByPhoneNumber(mobileNumber);
    }



    /**
     * 用户积分增加
     *
     * @param mobileNumber 手机号码
     * @param score        积分
     */
    @Transactional
    void add(String mobileNumber, Integer score) {
        // 增加用户积分
        int updateRowsAffected = userMapper.additionScore(mobileNumber, score);
        System.out.println("updateRowsAffected: " + updateRowsAffected);
        if (updateRowsAffected > 0) {
            // 说明找到了对应的手机号 ， 要去修改明细表状态
            scoreImportDetailMapper.changeSuccessByMobileNumber(mobileNumber);
            log.info("用户积分增加，手机号" + mobileNumber + ", 积分:" + score);
        } else {
            // 说明没找到对应的手机号
            // 不需要做操作
            log.info("未在用户表中找到该手机号：" + mobileNumber);
        }

    }



    /**
     * 用户积分增加(通过绑定)
     *
     * @param openId 微信ID
     * @param totalScore  积分
     */
    @Transactional
    boolean binding(String openId, String mobileNumber, Integer totalScore) {

        // (1) 修改用户表积分
        int updateAffected = userMapper.addScoreByOpenId(openId, totalScore);
        // (2) 修改明细表状态
        scoreImportDetailMapper.changeSuccessByMobileNumber(mobileNumber);
        log.info("用户积分绑定，手机号:" +  mobileNumber);
        return updateAffected > 0;

    }




}
